//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useRef, useState } from 'react';
import { observer } from 'mobx-react';
import { useDataViewStores } from '../../store';
import { Badge, Button, Card, message, Modal, Popover, Space } from 'antd';
import { CaretDownFilled, CaretUpFilled, MoreOutlined } from '@ant-design/icons';
import { type ChatMsgInfo, list_msg, get_msg, send_msg, update_msg, LIST_TYPE_BEFORE, LIST_TYPE_AFTER } from '@/api/dataview_chat';
import { request } from '@/utils/request';
import { get_session } from '@/api/user';
import moment from 'moment';
import { is_empty_doc, ReadOnlyEditor, useCommonEditor } from '@/components/Editor';
import { FILE_OWNER_TYPE_NONE } from '@/api/fs';
import UserPhoto from '@/components/Portrait/UserPhoto';
import { listen } from '@tauri-apps/api/event';
import type * as NoticeType from '@/api/notice_type';

interface EditMsgModalProps {
    projectId: string;
    viewId: string;
    msg: ChatMsgInfo;
    onClose: () => void;
}

const EditMsgModal = (props: EditMsgModalProps) => {

    const { editor, editorRef } = useCommonEditor({
        content: props.msg.content,
        fsId: "",
        ownerType: FILE_OWNER_TYPE_NONE,
        ownerId: props.viewId,
        historyInToolbar: false,
        clipboardInToolbar: false,
        commonInToolbar: false,
        pubResInToolbar: false,
    });

    const updateMsg = async () => {
        const content = editorRef.current?.getContent() ?? { type: "doc" };
        if (is_empty_doc(content)) {
            message.warn("讨论内容为空");
            return;
        }
        const contentStr = JSON.stringify(content);
        if (contentStr == props.msg.content) {
            message.warn("讨论内容未修改");
            return;
        }
        const sessionId = await get_session();
        await request(update_msg({
            session_id: sessionId,
            project_id: props.projectId,
            view_id: props.viewId,
            msg_id: props.msg.msg_id,
            content: contentStr,
        }));
        message.info("修改成功");
        props.onClose();
    };

    return (
        <Modal open title="修改内容" mask={false}
            okText="修改"
            onCancel={e => {
                e.stopPropagation();
                e.preventDefault();
                props.onClose();
            }}
            onOk={e => {
                e.stopPropagation();
                e.preventDefault();
                updateMsg();
            }}>
            <div className="_commentContext">
                {editor}
            </div>
        </Modal>
    );
};



interface ChatMsgViewProps {
    msg: ChatMsgInfo;
    wrapDiv: HTMLDivElement | null;
}

const ChatMsgView = observer((props: ChatMsgViewProps) => {
    const dataViewStore = useDataViewStores();

    const [showEditModal, setShowEditModal] = useState(false);

    useEffect(() => {
        if (props.wrapDiv == null) {
            return;
        }
        if (props.wrapDiv.clientHeight >= props.wrapDiv.scrollHeight) {
            return;
        }
        if (dataViewStore.chatStore.lastMsgId == props.msg.msg_id && dataViewStore.chatStore.initLoad == true) {
            dataViewStore.chatStore.initLoad = false;
            props.wrapDiv.scrollTo({ top: props.wrapDiv.scrollHeight });
            return;
        }
        const bottomDiff = props.wrapDiv.scrollHeight - props.wrapDiv.clientHeight - props.wrapDiv.scrollTop;
        if (bottomDiff < 100 && dataViewStore.chatStore.lastMsgId == props.msg.msg_id) {
            props.wrapDiv.scrollTo({ top: props.wrapDiv.scrollHeight });
        }
    }, [props.wrapDiv, dataViewStore.chatStore.lastMsgId, dataViewStore.chatStore.initLoad, props.msg.msg_id]);

    return (
        <Card bordered={false} title={<Space>
            <UserPhoto logoUri={props.msg.send_logo_uri} style={{ width: "20px", borderRadius: "10px" }} />
            {props.msg.send_display_name}
        </Space>}
            headStyle={{ backgroundColor: "#eee" }}
            extra={
                <Space>
                    {moment(props.msg.send_time).format("YYYY-MM-DD HH:mm:ss")}
                    {props.msg.has_changed == true && <span>已修改</span>}
                    {props.msg.has_changed == false && props.msg.send_user_id == dataViewStore.projectStore.myUserId &&
                        dataViewStore.projectStore.projectInfo != null && dataViewStore.projectStore.projectInfo.closed == false && (
                            <Popover trigger="click" placement='bottom' content={
                                <Space direction='vertical'>
                                    <Button type="link" onClick={e => {
                                        e.stopPropagation();
                                        e.preventDefault();
                                        setShowEditModal(true);
                                    }}>修改</Button>
                                </Space>
                            }>
                                <MoreOutlined />
                            </Popover>
                        )}
                </Space>
            }>
            <ReadOnlyEditor content={props.msg.content} />
            {showEditModal == true && (
                <EditMsgModal projectId={dataViewStore.projectStore.projectId} viewId={dataViewStore.projectStore.dataViewId} msg={props.msg}
                    onClose={() => setShowEditModal(false)} />
            )}
        </Card>
    );
});

const ChatPanel = () => {
    const dataViewStore = useDataViewStores();

    const chatWrapRef = useRef<HTMLDivElement>(null);

    const [inLoad, setInLoad] = useState(false);

    const { editor, editorRef } = useCommonEditor({
        content: "",
        fsId: "",
        ownerType: FILE_OWNER_TYPE_NONE,
        ownerId: dataViewStore.projectStore.dataViewId,
        historyInToolbar: false,
        clipboardInToolbar: false,
        commonInToolbar: false,
        pubResInToolbar: false,
    });

    const initMsgList = async () => {
        const sessionId = await get_session();
        const res = await request(list_msg({
            session_id: sessionId,
            project_id: dataViewStore.projectStore.projectId,
            view_id: dataViewStore.projectStore.dataViewId,
            list_type: LIST_TYPE_BEFORE,
            list_ref_time: moment().valueOf() + 10 * 365 * 24 * 3600 * 1000,
            limit: 20,
        }));
        dataViewStore.chatStore.msgList = res.msg_list;
        dataViewStore.chatStore.lastMsgId = res.last_msg_id;
        dataViewStore.chatStore.initLoad = true;
    };

    const sendMsg = async () => {
        const content = editorRef.current?.getContent() ?? { type: "doc" };
        if (is_empty_doc(content)) {
            message.warn("讨论内容为空");
            return;
        }
        const sessionId = await get_session();
        await request(send_msg({
            session_id: sessionId,
            project_id: dataViewStore.projectStore.projectId,
            view_id: dataViewStore.projectStore.dataViewId,
            content: JSON.stringify(content),
        }));
        editorRef.current?.setContent("");
    };

    const onNewMsg = async () => {
        const tmpMsgList = dataViewStore.chatStore.msgList.slice();
        if (tmpMsgList.length == 0) {
            await initMsgList();
            return;
        }
        const sessionId = await get_session();
        const res = await request(list_msg({
            session_id: sessionId,
            project_id: dataViewStore.projectStore.projectId,
            view_id: dataViewStore.projectStore.dataViewId,
            list_type: LIST_TYPE_AFTER,
            list_ref_time: tmpMsgList[tmpMsgList.length - 1].send_time,
            limit: 20,
        }));
        dataViewStore.chatStore.msgList = [...tmpMsgList, ...res.msg_list];
        dataViewStore.chatStore.lastMsgId = res.last_msg_id;
    };

    const onUpdateMsg = async (msgId: string) => {
        const tmpMsgList = dataViewStore.chatStore.msgList.slice();
        const index = tmpMsgList.findIndex(item => item.msg_id == msgId);
        if (index == -1) {
            return;
        }
        const sessionId = await get_session();
        const res = await request(get_msg({
            session_id: sessionId,
            project_id: dataViewStore.projectStore.projectId,
            view_id: dataViewStore.projectStore.dataViewId,
            msg_id: msgId,
        }));

        tmpMsgList[index] = res.msg;
        dataViewStore.chatStore.msgList = tmpMsgList;
    };

    const loadBeforeMsg = async () => {
        if (inLoad || dataViewStore.chatStore.msgList.length == 0) {
            return;
        }
        const tmpMsgList = dataViewStore.chatStore.msgList.slice();
        let newCount = 0;
        try {
            setInLoad(true);
            const sessionId = await get_session();
            const res = await request(list_msg({
                session_id: sessionId,
                project_id: dataViewStore.projectStore.projectId,
                view_id: dataViewStore.projectStore.dataViewId,
                list_type: LIST_TYPE_BEFORE,
                list_ref_time: tmpMsgList[0].send_time,
                limit: 20,
            }));
            dataViewStore.chatStore.msgList = [...res.msg_list, ...tmpMsgList];
            dataViewStore.chatStore.lastMsgId = res.last_msg_id;
            newCount = res.msg_list.length;
        } finally {
            if (newCount == 0) {
                setTimeout(() => {
                    setInLoad(false);
                }, 1000);
            } else {
                setInLoad(false);
            }
        }
    };

    const loadAfterMsg = async () => {
        if (inLoad || dataViewStore.chatStore.msgList.length == 0) {
            return;
        }
        const tmpMsgList = dataViewStore.chatStore.msgList.slice();
        let newCount = 0;
        try {
            setInLoad(true);
            const sessionId = await get_session();
            const res = await request(list_msg({
                session_id: sessionId,
                project_id: dataViewStore.projectStore.projectId,
                view_id: dataViewStore.projectStore.dataViewId,
                list_type: LIST_TYPE_AFTER,
                list_ref_time: tmpMsgList[tmpMsgList.length - 1].send_time,
                limit: 20,
            }));
            dataViewStore.chatStore.msgList = [...tmpMsgList, ...res.msg_list];
            dataViewStore.chatStore.lastMsgId = res.last_msg_id;
            newCount = res.msg_list.length;
        } finally {
            if (newCount == 0) {
                setTimeout(() => {
                    setInLoad(false);
                }, 1000);
            } else {
                setInLoad(false);
            }
        }
    };

    const onScroll = () => {
        if (chatWrapRef.current == null) {
            return;
        }
        if (chatWrapRef.current.scrollTop < 100) {
            loadBeforeMsg();
            return;
        }
        const bottomDiff = chatWrapRef.current.scrollHeight - chatWrapRef.current.clientHeight - chatWrapRef.current.scrollTop;
        if (bottomDiff < 100) {
            loadAfterMsg();
        }
    };

    useEffect(() => {
        const newMsgIdList: string[] = [];  //防止重复通知

        const unListenFn = listen<NoticeType.AllNotice>("notice", ev => {
            const notice = ev.payload;
            if (notice.DataviewNotice?.NewChatMsgNotice != undefined &&
                notice.DataviewNotice.NewChatMsgNotice.project_id == dataViewStore.projectStore.projectId &&
                notice.DataviewNotice.NewChatMsgNotice.view_id == dataViewStore.projectStore.dataViewId) {
                if (dataViewStore.chatStore.expand) {
                    onNewMsg();
                } else {
                    if (newMsgIdList.includes(notice.DataviewNotice.NewChatMsgNotice.msg_id) == false) {
                        dataViewStore.chatStore.unReadCount += 1;
                        newMsgIdList.push(notice.DataviewNotice.NewChatMsgNotice.msg_id);
                    }
                    while (newMsgIdList.length > 20) {
                        newMsgIdList.shift();
                    }
                }
            } else if (notice.DataviewNotice?.UpdateChatMsgNotice != undefined &&
                notice.DataviewNotice.UpdateChatMsgNotice.project_id == dataViewStore.projectStore.projectId &&
                notice.DataviewNotice.UpdateChatMsgNotice.view_id == dataViewStore.projectStore.dataViewId) {
                onUpdateMsg(notice.DataviewNotice.UpdateChatMsgNotice.msg_id);
            }
        });
        return () => {
            unListenFn.then((unListen) => unListen());
        };
    }, []);

    return (
        <div>
            {dataViewStore.chatStore.expand == false && (
                <Space style={{ cursor: "pointer", backgroundColor: "white", padding: "2px 10px 2px 40px" }} onClick={e => {
                    e.stopPropagation();
                    e.preventDefault();
                    dataViewStore.chatStore.expand = true;
                    dataViewStore.chatStore.unReadCount = 0;
                    initMsgList();
                }}>
                    <Badge count={dataViewStore.chatStore.unReadCount} overflowCount={99} offset={[-84, 8]} size='small'>
                        <span style={{ fontSize: "16px" }}>沟通记录</span>
                    </Badge>
                    <CaretUpFilled style={{ fontSize: "24px" }} />
                </Space>
            )}
            {dataViewStore.chatStore.expand == true && (
                <Card title="沟通记录"
                    bodyStyle={{ width: "400px" }}
                    extra={
                        <Button type="text" icon={<CaretDownFilled style={{ fontSize: "24px" }} />} onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            dataViewStore.chatStore.expand = false;
                        }} title='收起' />
                    }>
                    <div style={{ height: "calc(100vh - 400px)", overflowY: "scroll" }} ref={chatWrapRef} onScroll={() => onScroll()}>
                        {dataViewStore.chatStore.msgList.map(msg => (
                            <ChatMsgView key={msg.msg_id} msg={msg} wrapDiv={chatWrapRef.current} />
                        ))}
                    </div>
                    {dataViewStore.projectStore.projectInfo != null && dataViewStore.projectStore.projectInfo.closed == false && (
                        <div className="_commentContext" style={{ position: "relative" }}>
                            {editor}
                            <Button type='primary' style={{ position: "absolute", right: "10px", bottom: "10px" }}
                                onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    sendMsg();
                                }}>发送</Button>
                        </div>
                    )}
                </Card>
            )}
        </div>
    );
};

export default observer(ChatPanel);